package com.scratch.common.service.web;

import com.alibaba.fastjson.JSON;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;


/**
 * Created by bpf on 2020/12/22.
 */
@Slf4j
public class HttpFilter implements Filter {

    private static final List<String> headList = Arrays.asList(
            "timestamp",
            "path",
            "version",
            "sign",
            "appKey",
            "Content-Type"
    );


    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        byte[] resByte = null;
        RequestWrapper requestWrapper = null;
        long t1 = System.nanoTime();
        try {
            requestWrapper = new RequestWrapper((HttpServletRequest) request);
            ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response);
            String requestBody = "";
            if (RequestMethod.POST.toString().equals(requestWrapper.getMethod())) {
                requestBody = requestWrapper.getRequestBody().length == 0 ? "" : new String(requestWrapper.getRequestBody(), request.getCharacterEncoding());
            } else {
                requestBody = JSON.toJSONString(requestWrapper.getParameterMap());
            }
            log.info("reqFeign[{}] -- url={} -- heads={} -- body={}", requestWrapper.getMethod(), requestWrapper.getRequestURL(), getHeads(requestWrapper), requestBody);
            chain.doFilter(requestWrapper, responseWrapper);
            resByte = responseWrapper.getResponseBody();
        } catch (Exception e) {
            throw new RuntimeException("日志过滤器异常");
        } finally {
            if (resByte != null && resByte.length != 0) {
                try {
                    response.getOutputStream().write(resByte);
                    response.getOutputStream().flush();
                    response.getOutputStream().close();
                } catch (IOException i) {
                    throw new RuntimeException("日志过滤器流操作异常");
                }
            }
            String res = "";
            try {
                res = new String(resByte, request.getCharacterEncoding());
            } catch (UnsupportedEncodingException u) {
                throw new RuntimeException("日志过滤器转码异常");
            }
            long t2 = System.nanoTime();
            log.info("resFeign[{}] -- url={}  -- body={}", String.format("%.1fms", (t2 - t1) / 1e6d), requestWrapper.getRequestURL(), res);
        }
    }


    /**
     * 获取头信息
     *
     * @param requestWrapper
     * @return
     */
    private String getHeads(RequestWrapper requestWrapper) {
        Enumeration headerNames = requestWrapper.getHeaderNames();
        List<String> resHeadList = new ArrayList<>();
        while (headerNames.hasMoreElements()) {
            String headerName = (String) headerNames.nextElement();
            if (headList.contains(headerName)) {
                resHeadList.add(headerName + " : " + requestWrapper.getHeader(headerName));
            }
        }
        return StringUtils.join(resHeadList,",");
    }
}
